﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using TagCore;
using HtmlAgilityPack;

namespace FreeDBQuery
{
    public class FreedbSearch : IMusicQuery
    {
        private string searchRoot = "http://www.freedb.org/freedb_search.php?";
        private string searchParams = "page=1&words={0}&allfields=NO{1}&allcats=YES&grouping=none";

        public FreedbSearch()
        {
        }

        public string Provider()
        {
            return "FreeDB";
        }

        public IMusicData[] Search(IMusicData data, QueryFields fields)
        {
            //page=1&words=jedward&allfields=NO&fields%5B%5D=artist&fields%5B%5D=title&allcats=YES&grouping=none'
            //page=1&words=%2210+cc%22+%22I%27m+not+in+love%22&allfields=NO&fields%5B%5D=artist&fields%5B%5D=title&allcats=YES&grouping=none
        //http://www.freedb.org/freedb_search.php?page=1&words=%2210+cc%22+%22I'm+not+in+love%22&allfields=NO&fields%5B%5D=artist&fields%5B%5D=title&allcats=YES&grouping=none

            // build search string
            string srch = string.Empty;
            string flds = string.Empty;

            if ((fields & QueryFields.Artist) == QueryFields.Artist)
            {
                srch = AddSearchValue(srch, string.Format(@"""{0}""", data.Artists[0]));
                flds += "&fields%5B%5D=artist";
            }
            if ((fields & QueryFields.Title) == QueryFields.Title)
            {
                srch = AddSearchValue(srch, string.Format(@"""{0}""", data.Title));
                flds += "&fields%5B%5D=title";
            }

            srch = HttpUtility.UrlEncode(srch);
            srch = srch.Replace("%20", "+");

            string url = searchRoot + string.Format(searchParams, srch, flds);
            //    "http://www.freedb.org/freedb_search.php?page=1&words=%22Enya%22+%22Book+Of+Days%22&allfields=NO&fields%5B%5D=artist&fields%5B%5D=title&allcats=YES&grouping=none";
                

            byte[] result = GetWebRequest(url);

            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            MemoryStream ms = new MemoryStream(result);
            doc.Load(ms);

            HtmlNodeCollection titles = doc.DocumentNode.SelectNodes("//table[@class='searchResultT1A']");
            HtmlNodeCollection details = doc.DocumentNode.SelectNodes("//table[@class='searchResultT2A']");

            List<IMusicData> results = new List<IMusicData>();
            if (titles != null && details != null)
            {
                if (titles.Count != details.Count)
                    throw new ApplicationException("title and details mismatch");


                for (int loop = 0; loop < titles.Count; loop++)
                {
                    FreedbResponse resp = new FreedbResponse(data, titles[loop], details[loop]);
                    results.Add(resp);
                }
            }            
            return results.ToArray();           
        }

        private string AddSearchValue(string srch, string val)
        {
            if (srch.Length > 0)
                srch += " ";
            srch += val;
            return srch;
        }

        private byte[] GetWebRequest(string url)
        {
            HttpWebRequest wr = WebRequest.Create(url) as HttpWebRequest;
            wr.Method = "GET";
            wr.Timeout = 60000;
            wr.AllowAutoRedirect = true;
            wr.Accept = "text/html, application/xhtml+xml, */*";
            wr.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";

            HttpWebResponse resp = wr.GetResponse() as HttpWebResponse;

            List<byte> bytes = new List<byte>();
            byte[] b = new byte[65535];
            using (Stream s = resp.GetResponseStream())
            {
                int cnt = 0;
                do
                {
                    cnt = s.Read(b, 0, b.Length);
                    for (int loop = 0; loop < cnt; loop++)
                        bytes.Add(b[loop]);
                }
                while (cnt > 0);
            }
            resp.Close();
            return bytes.ToArray();
        }

    }
}
